package ua.edu.nuos.tees.jdmmon.bl;

import jssc.SerialPortException;
import ua.edu.nuos.tees.jdmmon.bl.timer.RefreshTask;
import ua.edu.nuos.tees.jdmmon.dao.exceptions.ConfigException;
import ua.edu.nuos.tees.jdmmon.dao.implementations.Rs232Dao;
import ua.edu.nuos.tees.jdmmon.dao.interfaces.Dao;
import ua.edu.nuos.tees.jdmmon.vo.MultimeterVo;
import utils.ConfigUtils;
import utils.ConfigurationLoader;
import vo.Config;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
import java.util.Timer;
import java.util.Vector;
import java.util.prefs.BackingStoreException;

/**
 * @author Timur Yarosh
 * @author Olha Mudrievska
 *         Date: 04.05.13
 *         Time: 11:14
 */
public class MultimeterService {
    private final MultimeterVo multimeterVo;
    private static final int BYTE_SIZE = 8;

    // Helga's registers
    private int PHASE_VOLTAGE_L1;
    private int PHASE_VOLTAGE_L2;
    private int PHASE_VOLTAGE_L3;
    private int TOTAL_ACTIVE_POWER;
    private int PHASE_VOLTAGE_HARMONICS_2_L1;
    private int PHASE_VOLTAGE_HARMONICS_2_L2;
    private int PHASE_VOLTAGE_HARMONICS_2_L3;
    private int PHASE_VOLTAGE_HARMONICS_3_L1;
    private int PHASE_VOLTAGE_HARMONICS_3_L2;
    private int PHASE_VOLTAGE_HARMONICS_3_L3;
    private int PHASE_VOLTAGE_HARMONICS_4_L1;
    private int PHASE_VOLTAGE_HARMONICS_4_L2;
    private int PHASE_VOLTAGE_HARMONICS_4_L3;
    private int PHASE_VOLTAGE_HARMONICS_5_L1;
    private int PHASE_VOLTAGE_HARMONICS_5_L2;
    private int PHASE_VOLTAGE_HARMONICS_5_L3;
    private int PHASE_VOLTAGE_HARMONICS_6_L1;
    private int PHASE_VOLTAGE_HARMONICS_6_L2;
    private int PHASE_VOLTAGE_HARMONICS_6_L3;
    private int PHASE_VOLTAGE_HARMONICS_7_L1;
    private int PHASE_VOLTAGE_HARMONICS_7_L2;
    private int PHASE_VOLTAGE_HARMONICS_7_L3;
    private int PHASE_VOLTAGE_HARMONICS_8_L1;
    private int PHASE_VOLTAGE_HARMONICS_8_L2;
    private int PHASE_VOLTAGE_HARMONICS_8_L3;
    private int PHASE_VOLTAGE_HARMONICS_9_L1;
    private int PHASE_VOLTAGE_HARMONICS_9_L2;
    private int PHASE_VOLTAGE_HARMONICS_9_L3;
    private int PHASE_VOLTAGE_HARMONICS_10_L1;
    private int PHASE_VOLTAGE_HARMONICS_10_L2;
    private int PHASE_VOLTAGE_HARMONICS_10_L3;
    private int PHASE_VOLTAGE_HARMONICS_11_L1;
    private int PHASE_VOLTAGE_HARMONICS_11_L2;
    private int PHASE_VOLTAGE_HARMONICS_11_L3;
    private int PHASE_VOLTAGE_HARMONICS_12_L1;
    private int THD_PHASE_VOLTAGE_L1;
    private int THD_PHASE_VOLTAGE_L2;
    private int THD_PHASE_VOLTAGE_L3;
    // Timur's registers
    private int PHASE_CURRENT_L1;
    private int PHASE_CURRENT_L2;
    private int PHASE_CURRENT_L3;
    private int TOTAL_REACTIVE_POWER;
    private int PHASE_VOLTAGE_HARMONICS_12_L2;
    private int PHASE_VOLTAGE_HARMONICS_12_L3;
    private int PHASE_VOLTAGE_HARMONICS_13_L1;
    private int PHASE_VOLTAGE_HARMONICS_13_L2;
    private int PHASE_VOLTAGE_HARMONICS_13_L3;
    private int PHASE_VOLTAGE_HARMONICS_14_L1;
    private int PHASE_VOLTAGE_HARMONICS_14_L2;
    private int PHASE_VOLTAGE_HARMONICS_14_L3;
    private int PHASE_VOLTAGE_HARMONICS_15_L1;
    private int PHASE_VOLTAGE_HARMONICS_15_L2;
    private int PHASE_VOLTAGE_HARMONICS_15_L3;
    private int PHASE_VOLTAGE_HARMONICS_16_L1;
    private int PHASE_VOLTAGE_HARMONICS_16_L2;
    private int PHASE_VOLTAGE_HARMONICS_16_L3;
    private int PHASE_VOLTAGE_HARMONICS_17_L1;
    private int PHASE_VOLTAGE_HARMONICS_17_L2;
    private int PHASE_VOLTAGE_HARMONICS_17_L3;
    private int PHASE_VOLTAGE_HARMONICS_18_L1;
    private int PHASE_VOLTAGE_HARMONICS_18_L2;
    private int PHASE_VOLTAGE_HARMONICS_18_L3;
    private int PHASE_VOLTAGE_HARMONICS_19_L1;
    private int PHASE_VOLTAGE_HARMONICS_19_L2;
    private int PHASE_VOLTAGE_HARMONICS_19_L3;
    private int PHASE_VOLTAGE_HARMONICS_20_L1;
    private int PHASE_VOLTAGE_HARMONICS_20_L2;
    private int PHASE_VOLTAGE_HARMONICS_20_L3;
    private int PHASE_VOLTAGE_HARMONICS_21_L1;
    private int PHASE_VOLTAGE_HARMONICS_21_L2;
    private int PHASE_VOLTAGE_HARMONICS_21_L3;
    private int PHASE_VOLTAGE_HARMONICS_22_L1;
    private int PHASE_VOLTAGE_HARMONICS_22_L2;
    private int PHASE_VOLTAGE_HARMONICS_22_L3;
    private int COS_PHI_L1;
    private int COS_PHI_L2;
    private int COS_PHI_L3;
    private int TOTAL_APPARENT_POWER;
    private int FREQUENCY;
    private int PHASE_TO_PHASE_VOLTAGE_L1_L2;
    private int PHASE_TO_PHASE_VOLTAGE_L2_L3;
    private int PHASE_TO_PHASE_VOLTAGE_L3_L1;

    private final Dao DAO;
    private Timer refreshTimer;
    private byte[] data;

    /**
     * @deprecated
     * @param deviceConfigInputStream
     * @param rs232
     * @throws ConfigException
     * @throws FileNotFoundException
     * @throws SerialPortException
     * @throws exceptions.ConfigException
     */
    public MultimeterService(InputStream deviceConfigInputStream, boolean rs232) throws ConfigException, FileNotFoundException, SerialPortException, exceptions.ConfigException {
        if (rs232) {
            DAO = new Rs232Dao(getClass().getResourceAsStream("/modbus_properties.ini"));
        } else {
            DAO = null;
        }
//        refreshTimer = new Timer("data refresh timer");
        Properties deviceConfig = ConfigurationLoader.loadConfig(deviceConfigInputStream);
        PHASE_VOLTAGE_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_L1"));
        PHASE_VOLTAGE_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_L2"));
        PHASE_VOLTAGE_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_L3"));
        TOTAL_ACTIVE_POWER = Integer.decode(deviceConfig.getProperty("TOTAL_ACTIVE_POWER"));
        PHASE_VOLTAGE_HARMONICS_2_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_2_L1"));
        PHASE_VOLTAGE_HARMONICS_2_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_2_L2"));
        PHASE_VOLTAGE_HARMONICS_2_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_2_L3"));
        PHASE_VOLTAGE_HARMONICS_3_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_3_L1"));
        PHASE_VOLTAGE_HARMONICS_3_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_3_L2"));
        PHASE_VOLTAGE_HARMONICS_3_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_3_L3"));
        PHASE_VOLTAGE_HARMONICS_4_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_4_L1"));
        PHASE_VOLTAGE_HARMONICS_4_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_4_L2"));
        PHASE_VOLTAGE_HARMONICS_4_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_4_L3"));
        PHASE_VOLTAGE_HARMONICS_5_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_5_L1"));
        PHASE_VOLTAGE_HARMONICS_5_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_5_L2"));
        PHASE_VOLTAGE_HARMONICS_5_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_5_L3"));
        PHASE_VOLTAGE_HARMONICS_6_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_6_L1"));
        PHASE_VOLTAGE_HARMONICS_6_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_6_L2"));
        PHASE_VOLTAGE_HARMONICS_6_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_6_L3"));
        PHASE_VOLTAGE_HARMONICS_7_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_7_L1"));
        PHASE_VOLTAGE_HARMONICS_7_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_7_L2"));
        PHASE_VOLTAGE_HARMONICS_7_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_7_L3"));
        PHASE_VOLTAGE_HARMONICS_8_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_8_L1"));
        PHASE_VOLTAGE_HARMONICS_8_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_8_L2"));
        PHASE_VOLTAGE_HARMONICS_8_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_8_L3"));
        PHASE_VOLTAGE_HARMONICS_9_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_9_L1"));
        PHASE_VOLTAGE_HARMONICS_9_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_9_L2"));
        PHASE_VOLTAGE_HARMONICS_9_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_9_L3"));
        PHASE_VOLTAGE_HARMONICS_10_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_10_L1"));
        PHASE_VOLTAGE_HARMONICS_10_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_10_L2"));
        PHASE_VOLTAGE_HARMONICS_10_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_10_L3"));
        PHASE_VOLTAGE_HARMONICS_11_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_11_L1"));
        PHASE_VOLTAGE_HARMONICS_11_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_11_L2"));
        PHASE_VOLTAGE_HARMONICS_11_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_11_L3"));
        PHASE_VOLTAGE_HARMONICS_12_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_12_L1"));
        PHASE_VOLTAGE_HARMONICS_12_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_12_L2"));
        PHASE_VOLTAGE_HARMONICS_12_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_12_L3"));
        THD_PHASE_VOLTAGE_L1 = Integer.decode(deviceConfig.getProperty("THD_PHASE_VOLTAGE_L1"));
        THD_PHASE_VOLTAGE_L2 = Integer.decode(deviceConfig.getProperty("THD_PHASE_VOLTAGE_L2"));
        THD_PHASE_VOLTAGE_L3 = Integer.decode(deviceConfig.getProperty("THD_PHASE_VOLTAGE_L3"));
        PHASE_CURRENT_L1 = Integer.decode(deviceConfig.getProperty("PHASE_CURRENT_L1"));
        PHASE_CURRENT_L2 = Integer.decode(deviceConfig.getProperty("PHASE_CURRENT_L2"));
        PHASE_CURRENT_L3 = Integer.decode(deviceConfig.getProperty("PHASE_CURRENT_L3"));
        TOTAL_REACTIVE_POWER = Integer.decode(deviceConfig.getProperty("TOTAL_REACTIVE_POWER"));
        PHASE_VOLTAGE_HARMONICS_13_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_13_L1"));
        PHASE_VOLTAGE_HARMONICS_13_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_13_L2"));
        PHASE_VOLTAGE_HARMONICS_13_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_13_L3"));
        PHASE_VOLTAGE_HARMONICS_14_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_14_L1"));
        PHASE_VOLTAGE_HARMONICS_14_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_14_L2"));
        PHASE_VOLTAGE_HARMONICS_14_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_14_L3"));
        PHASE_VOLTAGE_HARMONICS_15_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_15_L1"));
        PHASE_VOLTAGE_HARMONICS_15_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_15_L2"));
        PHASE_VOLTAGE_HARMONICS_15_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_15_L3"));
        PHASE_VOLTAGE_HARMONICS_16_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_16_L1"));
        PHASE_VOLTAGE_HARMONICS_16_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_16_L2"));
        PHASE_VOLTAGE_HARMONICS_16_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_16_L3"));
        PHASE_VOLTAGE_HARMONICS_17_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_17_L1"));
        PHASE_VOLTAGE_HARMONICS_17_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_17_L2"));
        PHASE_VOLTAGE_HARMONICS_17_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_17_L3"));
        PHASE_VOLTAGE_HARMONICS_18_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_18_L1"));
        PHASE_VOLTAGE_HARMONICS_18_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_18_L2"));
        PHASE_VOLTAGE_HARMONICS_18_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_18_L3"));
        PHASE_VOLTAGE_HARMONICS_19_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_19_L1"));
        PHASE_VOLTAGE_HARMONICS_19_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_19_L2"));
        PHASE_VOLTAGE_HARMONICS_19_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_19_L3"));
        PHASE_VOLTAGE_HARMONICS_20_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_20_L1"));
        PHASE_VOLTAGE_HARMONICS_20_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_20_L2"));
        PHASE_VOLTAGE_HARMONICS_20_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_20_L3"));
        PHASE_VOLTAGE_HARMONICS_21_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_21_L1"));
        PHASE_VOLTAGE_HARMONICS_21_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_21_L2"));
        PHASE_VOLTAGE_HARMONICS_21_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_21_L3"));
        PHASE_VOLTAGE_HARMONICS_22_L1 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_22_L1"));
        PHASE_VOLTAGE_HARMONICS_22_L2 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_22_L2"));
        PHASE_VOLTAGE_HARMONICS_22_L3 = Integer.decode(deviceConfig.getProperty("PHASE_VOLTAGE_HARMONICS_22_L3"));
        COS_PHI_L1 = Integer.decode(deviceConfig.getProperty("COS_PHI_L1"));
        COS_PHI_L2 = Integer.decode(deviceConfig.getProperty("COS_PHI_L2"));
        COS_PHI_L3 = Integer.decode(deviceConfig.getProperty("COS_PHI_L3"));
        TOTAL_APPARENT_POWER = Integer.decode(deviceConfig.getProperty("TOTAL_APPARENT_POWER"));
        FREQUENCY = Integer.decode(deviceConfig.getProperty("FREQUENCY"));
        PHASE_TO_PHASE_VOLTAGE_L1_L2 = Integer.decode(deviceConfig.getProperty("PHASE_TO_PHASE_VOLTAGE_L1_L2"));
        PHASE_TO_PHASE_VOLTAGE_L2_L3 = Integer.decode(deviceConfig.getProperty("PHASE_TO_PHASE_VOLTAGE_L2_L3"));
        PHASE_TO_PHASE_VOLTAGE_L3_L1 = Integer.decode(deviceConfig.getProperty("PHASE_TO_PHASE_VOLTAGE_L3_L1"));
        multimeterVo = MultimeterVo.getInstance();
    }

    public MultimeterService(Config rs232Config, Config modbusConfig, Config deviceConfig, boolean rs232) throws ConfigException, FileNotFoundException, SerialPortException, exceptions.ConfigException {
        if (rs232) {
            DAO = new Rs232Dao(rs232Config, modbusConfig);
        } else {
            DAO = null;
        }
//        refreshTimer = new Timer("data refresh timer");
        setDeviceConfig(deviceConfig);
        multimeterVo = MultimeterVo.getInstance();
    }


    /**
     * Get current instance of DAO
     * @return current instance of DAO
     */
    public Dao getDAO() {
        return this.DAO;
    }


    public static List<String> listInstalledDevices() throws BackingStoreException {
        List<String> devices = new Vector<>();
        String[] preferences = ConfigUtils.listConfigs();
        for (String preference : preferences) {
            if (preference.contains("devices")) {
                String deviceName = preference.substring(preference.indexOf("devices/"), preference.length());
                deviceName = deviceName.replace("devices/", "");
                devices.add(deviceName);
            }
        }
        return devices;
    }

    /**
     * Start data auto refreshing
     * @param ms refresh period in milliseconds
     */
    public void startAutoRefreshing(long ms) {
        refreshTimer = new Timer();
        RefreshTask refreshTask = new RefreshTask(this);
        refreshTimer.schedule(refreshTask, 0, ms);
    }

    /**
     * Stop data auto refreshing
     */
    public void stopAutoRefreshing() {
        refreshTimer.cancel();
    }

    /**
     * Invoke all methods that refresh multimeter data
     * @throws InterruptedException
     * @throws SerialPortException if and error occurred when I/O to rs-232
     * @throws IOException if and error occurred when I/O to local storage
     */
    public void refreshData() throws InterruptedException, SerialPortException, IOException {
        data = DAO.getData();
//        refreshCosPhiL1();
//        refreshCosPhiL2();
//        refreshCosPhiL3();
        refreshPhaseCurrentL1();
        refreshPhaseCurrentL2();
        refreshPhaseCurrentL3();
        refreshPhaseVoltageL1();
        refreshPhaseVoltageL2();
        refreshPhaseVoltageL3();
//        refreshPhaseVoltageHarmonics2L1();
//        refreshPhaseVoltageHarmonics2L2();
//        refreshPhaseVoltageHarmonics2L3();
//        refreshPhaseVoltageHarmonics3L1();
//        refreshPhaseVoltageHarmonics3L2();
//        refreshPhaseVoltageHarmonics3L3();
//        refreshPhaseVoltageHarmonics4L1();
//        refreshPhaseVoltageHarmonics4L2();
//        refreshPhaseVoltageHarmonics4L3();
//        refreshPhaseVoltageHarmonics5L1();
//        refreshPhaseVoltageHarmonics5L2();
//        refreshPhaseVoltageHarmonics5L3();
//        refreshPhaseVoltageHarmonics6L1();
//        refreshPhaseVoltageHarmonics6L2();
//        refreshPhaseVoltageHarmonics6L3();
//        refreshPhaseVoltageHarmonics7L1();
//        refreshPhaseVoltageHarmonics7L2();
//        refreshPhaseVoltageHarmonics7L3();
//        refreshPhaseVoltageHarmonics8L1();
//        refreshPhaseVoltageHarmonics8L2();
//        refreshPhaseVoltageHarmonics8L3();
//        refreshPhaseVoltageHarmonics9L1();
//        refreshPhaseVoltageHarmonics9L2();
//        refreshPhaseVoltageHarmonics9L3();
//        refreshPhaseVoltageHarmonics10L1();
//        refreshPhaseVoltageHarmonics10L2();
//        refreshPhaseVoltageHarmonics10L3();
//        refreshPhaseVoltageHarmonics11L1();
//        refreshPhaseVoltageHarmonics11L2();
//        refreshPhaseVoltageHarmonics11L3();
//        refreshPhaseVoltageHarmonics12L1();
//        refreshPhaseVoltageHarmonics12L2();
//        refreshPhaseVoltageHarmonics12L3();
//        refreshPhaseVoltageHarmonics13L1();
//        refreshPhaseVoltageHarmonics13L2();
//        refreshPhaseVoltageHarmonics13L3();
//        refreshPhaseVoltageHarmonics14L1();
//        refreshPhaseVoltageHarmonics14L2();
//        refreshPhaseVoltageHarmonics14L3();
//        refreshPhaseVoltageHarmonics15L1();
//        refreshPhaseVoltageHarmonics15L2();
//        refreshPhaseVoltageHarmonics15L3();
//        refreshPhaseVoltageHarmonics16L1();
//        refreshPhaseVoltageHarmonics16L2();
//        refreshPhaseVoltageHarmonics16L3();
//        refreshPhaseVoltageHarmonics17L1();
//        refreshPhaseVoltageHarmonics17L2();
//        refreshPhaseVoltageHarmonics17L3();
//        refreshPhaseVoltageHarmonics18L1();
//        refreshPhaseVoltageHarmonics18L2();
//        refreshPhaseVoltageHarmonics18L3();
//        refreshPhaseVoltageHarmonics19L1();
//        refreshPhaseVoltageHarmonics19L2();
//        refreshPhaseVoltageHarmonics19L3();
//        refreshPhaseVoltageHarmonics20L1();
//        refreshPhaseVoltageHarmonics20L2();
//        refreshPhaseVoltageHarmonics20L3();
//        refreshPhaseVoltageHarmonics21L1();
//        refreshPhaseVoltageHarmonics21L2();
//        refreshPhaseVoltageHarmonics21L3();
//        refreshPhaseVoltageHarmonics22L1();
//        refreshPhaseVoltageHarmonics22L2();
//        refreshPhaseVoltageHarmonics22L3();
//        refreshTHDPhaseVoltageL1();
//        refreshTHDPhaseVoltageL2();
//        refreshTHDPhaseVoltageL3();
        refreshTotalActivePower();
        refreshTotalReactivePower();
        refreshTotalApparentPower();
//        refreshFrequency();
        refreshPhaseToPhaseVoltageL1L2();
        refreshPhaseToPhaseVoltageL2L3();
        refreshPhaseToPhaseVoltageL3L1();
    }

    /**
     * Refresh L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                                  if CRC of received data not equals with expected CRC
     * @throws jssc.SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageL1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageL1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_L1 - 1) * 2], data[PHASE_VOLTAGE_L1 * 2 - 1]}));
    }

    /**
     * Refresh L2 phase voltage
     *
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageL2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageL2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_L2 - 1) * 2], data[PHASE_VOLTAGE_L2 * 2 - 1]}));
    }

    /**
     * Refresh L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageL3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageL3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_L3 - 1) * 2], data[PHASE_VOLTAGE_L3 * 2 - 1]}));
    }

    /**
     * Refresh total active power
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshTotalActivePower() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setTotalActivePower(bytesArrayToNumber(
                new byte[] {data[(TOTAL_ACTIVE_POWER - 1) * 2], data[TOTAL_ACTIVE_POWER * 2 - 1]}));
    }

    /**
     * Refresh 2 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics2L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics2L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_2_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_2_L1 * 2 - 1]}));
    }

    /**
     * Refresh 2 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics2L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics2L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_2_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_2_L2 * 2 - 1]}));
    }

    /**
     * Refresh 2 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics2L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics2L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_2_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_2_L3 * 2 - 1]}));
    }

    /**
     * Refresh 3 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics3L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics3L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_3_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_3_L1 * 2 - 1]}));
    }

    /**
     * Refresh 3 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics3L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics3L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_3_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_3_L2 * 2 - 1]}));
    }

    /**
     * Refresh 3 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics3L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics3L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_3_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_3_L3 * 2 - 1]}));
    }

    /**
     * Refresh 4 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics4L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics4L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_4_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_4_L1 * 2 - 1]}));
    }

    /**
     * Refresh 4 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics4L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics4L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_4_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_4_L2 * 2 - 1]}));
    }

    /**
     * Refresh 4 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics4L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics4L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_4_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_4_L3 * 2 - 1]}));
    }

    /**
     * Refresh 5 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics5L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics5L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_5_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_5_L1 * 2 - 1]}));
    }

    /**
     * Refresh 5 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics5L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics5L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_5_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_5_L2 * 2 - 1]}));
    }

    /**
     * Refresh 5 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics5L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics5L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_5_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_5_L3 * 2 - 1]}));
    }

    /**
     * Refresh 6 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics6L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics6L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_6_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_6_L1 * 2 - 1]}));
    }

    /**
     * Refresh 6 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics6L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics6L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_6_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_6_L2 * 2 - 1]}));
    }

    /**
     * Refresh 6 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics6L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics6L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_6_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_6_L3 * 2 - 1]}));
    }

    /**
     * Refresh 7 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics7L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics7L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_7_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_7_L1 * 2 - 1]}));
    }

    /**
     * Refresh 7 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics7L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics7L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_7_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_7_L2 * 2 - 1]}));
    }

    /**
     * Refresh 7 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics7L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics7L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_7_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_7_L3 * 2 - 1]}));
    }

    /**
     * Refresh 8 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics8L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics8L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_8_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_8_L1 * 2 - 1]}));
    }

    /**
     * Refresh 8 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics8L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics8L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_8_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_8_L2 * 2 - 1]}));
    }

    /**
     * Refresh 8 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics8L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics8L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_8_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_8_L3 * 2 - 1]}));
    }

    /**
     * Refresh 9 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics9L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics9L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_9_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_9_L1 * 2 - 1]}));
    }

    /**
     * Refresh 9 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics9L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics9L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_9_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_9_L2 * 2 - 1]}));
    }

    /**
     * Refresh 9 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics9L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics9L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_9_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_9_L3 * 2 - 1]}));
    }

    /**
     * Refresh 10 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics10L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics10L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_10_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_10_L1 * 2 - 1]}));
    }

    /**
     * Refresh 10 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics10L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics10L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_10_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_10_L2 * 2 - 1]}));
    }

    /**
     * Refresh 10 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics10L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics10L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_10_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_10_L3 * 2 - 1]}));
    }

    /**
     * Refresh 11 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics11L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics11L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_11_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_11_L1 * 2 - 1]}));
    }

    /**
     * Refresh 11 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics11L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics11L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_11_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_11_L2 * 2 - 1]}));
    }

    /**
     * Refresh 11 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics11L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics11L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_11_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_11_L3 * 2 - 1]}));
    }

    /**
     * Refresh 12 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics12L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics12L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_12_L1 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_12_L1 * 2 - 1]}));
    }

    /**
     * Refresh 12 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics12L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics12L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_12_L2 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_12_L2 * 2 - 1]}));
    }

    /**
     * Refresh 12 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics12L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics12L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_12_L3 - 1) * 2], data[PHASE_VOLTAGE_HARMONICS_12_L3 * 2 - 1]}));
    }

    /**
     * Refresh THD phase voltage L1
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshTHDPhaseVoltageL1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setThdPhaseVoltageL1(bytesArrayToNumber(
                new byte[] {data[(THD_PHASE_VOLTAGE_L1 - 1) * 2], data[THD_PHASE_VOLTAGE_L1 * 2 - 1]}));
    }

    /**
     * Refresh THD phase voltage L2
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshTHDPhaseVoltageL2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setThdPhaseVoltageL2(bytesArrayToNumber(
                new byte[] {data[(THD_PHASE_VOLTAGE_L2 - 1) * 2], data[THD_PHASE_VOLTAGE_L2 * 2 - 1]}));
    }

    /**
     * Refresh THD phase voltage L3
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshTHDPhaseVoltageL3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setThdPhaseVoltageL3(bytesArrayToNumber(
                new byte[] {data[(THD_PHASE_VOLTAGE_L3 - 1) * 2], data[THD_PHASE_VOLTAGE_L3 * 2 - 1]}));
    }

    /**
     * Refresh L1 phase current
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseCurrentL1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseCurrentL1(bytesArrayToNumber(
                new byte[] {data[(PHASE_CURRENT_L1 - 1) * 2], data[PHASE_CURRENT_L1 * 2 - 1]}));
    }

    /**
     * Refresh L2 phase current
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseCurrentL2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseCurrentL2(bytesArrayToNumber(
                new byte[] {data[(PHASE_CURRENT_L2 - 1) * 2], data[PHASE_CURRENT_L2 * 2 - 1]}));
    }

    /**
     * Refresh L3 phase current
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseCurrentL3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseCurrentL3(bytesArrayToNumber(
                new byte[] {data[(PHASE_CURRENT_L3 - 1) * 2], data[PHASE_CURRENT_L3 * 2 - 1]}));
    }

    /**
     * Refresh total reactive power
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshTotalReactivePower() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setTotalReactivePower(bytesArrayToNumber(
                new byte[] {data[(TOTAL_REACTIVE_POWER - 1) * 2], data[TOTAL_REACTIVE_POWER * 2 - 1]}));
    }

    /**
     * Refresh 13 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics13L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics13L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_13_L1 - 1) * 2],
                       data[PHASE_VOLTAGE_HARMONICS_13_L1 * 2 - 1]}));
    }

    /**
     * Refresh 13 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics13L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics13L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_13_L2 - 1) * 2],
                       data[PHASE_VOLTAGE_HARMONICS_13_L2 * 2 - 1]}));
    }

    /**
     * Refresh 13 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics13L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics13L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_13_L3 - 1) * 2],
                       data[PHASE_VOLTAGE_HARMONICS_13_L3 * 2 - 1]}));
    }

    /**
     * Refresh 14 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics14L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics14L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_14_L1 - 1) * 2],
                       data[PHASE_VOLTAGE_HARMONICS_14_L1 * 2 - 1]}));
    }

    /**
     * Refresh 14 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics14L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics14L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_14_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_14_L2 * 2 - 1]}));
    }

    /**
     * Refresh 14 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics14L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics14L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_14_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_14_L3 * 2 - 1]}));
    }

    /**
     * Refresh 15 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics15L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics15L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_15_L1 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_15_L1 * 2 - 1]}));
    }

    /**
     * Refresh 15 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics15L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics15L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_15_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_15_L2 * 2 - 1]}));
    }

    /**
     * Refresh 15 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics15L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics15L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_15_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_15_L3 * 2 - 1]}));
    }

    /**
     * Refresh 16 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics16L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics16L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_16_L1 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_16_L1 * 2 - 1]}));
    }

    /**
     * Refresh 16 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics16L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics16L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_16_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_16_L2 * 2 - 1]}));
    }

    /**
     * Refresh 16 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics16L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics16L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_16_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_16_L3 * 2 - 1]}));
    }

    /**
     * Refresh 17 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics17L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics17L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_17_L1 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_17_L1 * 2 - 1]}));
    }

    /**
     * Refresh 17 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics17L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics17L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_17_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_17_L2 * 2 - 1]}));
    }

    /**
     * Refresh 17 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics17L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics17L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_17_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_17_L3 * 2 - 1]}));
    }

    /**
     * Refresh 18 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics18L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics18L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_18_L1 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_18_L1 * 2 - 1]}));
    }

    /**
     * Refresh 18 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics18L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics18L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_18_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_18_L2 * 2 - 1]}));
    }

    /**
     * Refresh 18 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics18L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics18L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_18_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_18_L3 * 2 - 1]}));
    }

    /**
     * Refresh 19 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *          if CRC of received data not equals with expected CRC
     */
    private void refreshPhaseVoltageHarmonics19L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics19L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_19_L1 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_19_L1 * 2 - 1]}));
    }

    /**
     * Refresh 19 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics19L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics19L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_19_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_19_L2 * 2 - 1]}));
    }

    /**
     * Refresh 19 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics19L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics19L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_19_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_19_L3 * 2 - 1]}));
    }

    /**
     * Refresh 20 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics20L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics20L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_20_L1 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_20_L1 * 2 - 1]}));
    }

    /**
     * Refresh 20 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics20L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics20L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_20_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_20_L2 * 2 - 1]}));
    }

    /**
     * Refresh 20 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics20L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics20L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_20_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_20_L3 * 2 - 1]}));
    }

    /**
     * Refresh 21 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics21L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics21L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_21_L1 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_21_L1 * 2 - 1]}));
    }

    /**
     * Refresh 21 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics21L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics21L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_21_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_21_L2 * 2 - 1]}));
    }

    /**
     * Refresh 21 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics21L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics21L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_21_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_21_L3 * 2 - 1]}));
    }

    /**
     * Refresh 22 harmonic on L1 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics22L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics22L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_22_L1 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_22_L1 * 2 - 1]}));
    }

    /**
     * Refresh 22 harmonic on L2 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics22L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics22L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_22_L2 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_22_L2 * 2 - 1]}));
    }

    /**
     * Refresh 22 harmonic on L3 phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseVoltageHarmonics22L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseVoltageHarmonics22L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_VOLTAGE_HARMONICS_22_L3 - 1) * 2],
                        data[PHASE_VOLTAGE_HARMONICS_22_L3 * 2 - 1]}));
    }

    /**
     * Refresh cos(phi) L1
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshCosPhiL1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setCosPhiL1(bytesArrayToNumber(
                new byte[] {data[(COS_PHI_L1 - 1) * 2], data[COS_PHI_L1 * 2 - 1]}));
    }

    /**
     * Refresh cos(phi) L2
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshCosPhiL2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setCosPhiL2(bytesArrayToNumber(
                new byte[] {data[(COS_PHI_L2 - 1) * 2], data[COS_PHI_L2 * 2 - 1]}));
    }

    /**
     * Refresh cos(phi) L3
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshCosPhiL3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setCosPhiL3(bytesArrayToNumber(
                new byte[] {data[(COS_PHI_L3 - 1) * 2], data[COS_PHI_L3 * 2 - 1]}));
    }

    /**
     * Refresh total apparent power
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshTotalApparentPower() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setTotalApparentPower(bytesArrayToNumber(
                new byte[] {data[(TOTAL_APPARENT_POWER - 1) * 2], data[TOTAL_APPARENT_POWER * 2 - 1]}));
    }

    /**
     * Refresh frequency
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshFrequency() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setFrequency(bytesArrayToNumber(
                new byte[] {data[(FREQUENCY - 1) * 2], data[FREQUENCY * 2 - 1]}));
    }

    /**
     * Refresh L1-L2 phase to phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseToPhaseVoltageL1L2() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseToPhaseVoltageL1L2(bytesArrayToNumber(
                new byte[] {data[(PHASE_TO_PHASE_VOLTAGE_L1_L2 - 1) * 2], data[PHASE_TO_PHASE_VOLTAGE_L1_L2 * 2 - 1]}));
    }

    /**
     * Refresh L2-L3 phase to phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseToPhaseVoltageL2L3() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseToPhaseVoltageL2L3(bytesArrayToNumber(
                new byte[] {data[(PHASE_TO_PHASE_VOLTAGE_L2_L3 - 1) * 2], data[PHASE_TO_PHASE_VOLTAGE_L2_L3 * 2 - 1]}));
    }

    /**
     * Refresh L3-L1 phase to phase voltage
     *
     * @throws ua.edu.nuos.tees.jdmmon.dao.exceptions.CRCException
     *                             if CRC of received data not equals with expected CRC
     * @throws SerialPortException if and error occurred when I/O to rs-232
     */
    private void refreshPhaseToPhaseVoltageL3L1() throws SerialPortException, InterruptedException, IOException {
        multimeterVo.setPhaseToPhaseVoltageL3L1(bytesArrayToNumber(
                new byte[] {data[(PHASE_TO_PHASE_VOLTAGE_L3_L1 - 1) * 2], data[PHASE_TO_PHASE_VOLTAGE_L3_L1 * 2 - 1]}));
    }

    public void setDeviceConfig(Config deviceConfig) {
        PHASE_VOLTAGE_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_L1"));
        PHASE_VOLTAGE_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_L2"));
        PHASE_VOLTAGE_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_L3"));
        TOTAL_ACTIVE_POWER = deviceConfig.getInteger(("TOTAL_ACTIVE_POWER"));
        PHASE_VOLTAGE_HARMONICS_2_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_2_L1"));
        PHASE_VOLTAGE_HARMONICS_2_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_2_L2"));
        PHASE_VOLTAGE_HARMONICS_2_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_2_L3"));
        PHASE_VOLTAGE_HARMONICS_3_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_3_L1"));
        PHASE_VOLTAGE_HARMONICS_3_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_3_L2"));
        PHASE_VOLTAGE_HARMONICS_3_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_3_L3"));
        PHASE_VOLTAGE_HARMONICS_4_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_4_L1"));
        PHASE_VOLTAGE_HARMONICS_4_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_4_L2"));
        PHASE_VOLTAGE_HARMONICS_4_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_4_L3"));
        PHASE_VOLTAGE_HARMONICS_5_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_5_L1"));
        PHASE_VOLTAGE_HARMONICS_5_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_5_L2"));
        PHASE_VOLTAGE_HARMONICS_5_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_5_L3"));
        PHASE_VOLTAGE_HARMONICS_6_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_6_L1"));
        PHASE_VOLTAGE_HARMONICS_6_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_6_L2"));
        PHASE_VOLTAGE_HARMONICS_6_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_6_L3"));
        PHASE_VOLTAGE_HARMONICS_7_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_7_L1"));
        PHASE_VOLTAGE_HARMONICS_7_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_7_L2"));
        PHASE_VOLTAGE_HARMONICS_7_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_7_L3"));
        PHASE_VOLTAGE_HARMONICS_8_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_8_L1"));
        PHASE_VOLTAGE_HARMONICS_8_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_8_L2"));
        PHASE_VOLTAGE_HARMONICS_8_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_8_L3"));
        PHASE_VOLTAGE_HARMONICS_9_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_9_L1"));
        PHASE_VOLTAGE_HARMONICS_9_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_9_L2"));
        PHASE_VOLTAGE_HARMONICS_9_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_9_L3"));
        PHASE_VOLTAGE_HARMONICS_10_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_10_L1"));
        PHASE_VOLTAGE_HARMONICS_10_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_10_L2"));
        PHASE_VOLTAGE_HARMONICS_10_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_10_L3"));
        PHASE_VOLTAGE_HARMONICS_11_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_11_L1"));
        PHASE_VOLTAGE_HARMONICS_11_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_11_L2"));
        PHASE_VOLTAGE_HARMONICS_11_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_11_L3"));
        PHASE_VOLTAGE_HARMONICS_12_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_12_L1"));
        PHASE_VOLTAGE_HARMONICS_12_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_12_L2"));
        PHASE_VOLTAGE_HARMONICS_12_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_12_L3"));
        THD_PHASE_VOLTAGE_L1 = deviceConfig.getInteger(("THD_PHASE_VOLTAGE_L1"));
        THD_PHASE_VOLTAGE_L2 = deviceConfig.getInteger(("THD_PHASE_VOLTAGE_L2"));
        THD_PHASE_VOLTAGE_L3 = deviceConfig.getInteger(("THD_PHASE_VOLTAGE_L3"));
        PHASE_CURRENT_L1 = deviceConfig.getInteger(("PHASE_CURRENT_L1"));
        PHASE_CURRENT_L2 = deviceConfig.getInteger(("PHASE_CURRENT_L2"));
        PHASE_CURRENT_L3 = deviceConfig.getInteger(("PHASE_CURRENT_L3"));
        TOTAL_REACTIVE_POWER = deviceConfig.getInteger(("TOTAL_REACTIVE_POWER"));
        PHASE_VOLTAGE_HARMONICS_13_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_13_L1"));
        PHASE_VOLTAGE_HARMONICS_13_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_13_L2"));
        PHASE_VOLTAGE_HARMONICS_13_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_13_L3"));
        PHASE_VOLTAGE_HARMONICS_14_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_14_L1"));
        PHASE_VOLTAGE_HARMONICS_14_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_14_L2"));
        PHASE_VOLTAGE_HARMONICS_14_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_14_L3"));
        PHASE_VOLTAGE_HARMONICS_15_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_15_L1"));
        PHASE_VOLTAGE_HARMONICS_15_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_15_L2"));
        PHASE_VOLTAGE_HARMONICS_15_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_15_L3"));
        PHASE_VOLTAGE_HARMONICS_16_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_16_L1"));
        PHASE_VOLTAGE_HARMONICS_16_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_16_L2"));
        PHASE_VOLTAGE_HARMONICS_16_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_16_L3"));
        PHASE_VOLTAGE_HARMONICS_17_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_17_L1"));
        PHASE_VOLTAGE_HARMONICS_17_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_17_L2"));
        PHASE_VOLTAGE_HARMONICS_17_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_17_L3"));
        PHASE_VOLTAGE_HARMONICS_18_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_18_L1"));
        PHASE_VOLTAGE_HARMONICS_18_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_18_L2"));
        PHASE_VOLTAGE_HARMONICS_18_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_18_L3"));
        PHASE_VOLTAGE_HARMONICS_19_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_19_L1"));
        PHASE_VOLTAGE_HARMONICS_19_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_19_L2"));
        PHASE_VOLTAGE_HARMONICS_19_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_19_L3"));
        PHASE_VOLTAGE_HARMONICS_20_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_20_L1"));
        PHASE_VOLTAGE_HARMONICS_20_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_20_L2"));
        PHASE_VOLTAGE_HARMONICS_20_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_20_L3"));
        PHASE_VOLTAGE_HARMONICS_21_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_21_L1"));
        PHASE_VOLTAGE_HARMONICS_21_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_21_L2"));
        PHASE_VOLTAGE_HARMONICS_21_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_21_L3"));
        PHASE_VOLTAGE_HARMONICS_22_L1 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_22_L1"));
        PHASE_VOLTAGE_HARMONICS_22_L2 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_22_L2"));
        PHASE_VOLTAGE_HARMONICS_22_L3 = deviceConfig.getInteger(("PHASE_VOLTAGE_HARMONICS_22_L3"));
        COS_PHI_L1 = deviceConfig.getInteger(("COS_PHI_L1"));
        COS_PHI_L2 = deviceConfig.getInteger(("COS_PHI_L2"));
        COS_PHI_L3 = deviceConfig.getInteger(("COS_PHI_L3"));
        TOTAL_APPARENT_POWER = deviceConfig.getInteger(("TOTAL_APPARENT_POWER"));
        FREQUENCY = deviceConfig.getInteger(("FREQUENCY"));
        PHASE_TO_PHASE_VOLTAGE_L1_L2 = deviceConfig.getInteger(("PHASE_TO_PHASE_VOLTAGE_L1_L2"));
        PHASE_TO_PHASE_VOLTAGE_L2_L3 = deviceConfig.getInteger(("PHASE_TO_PHASE_VOLTAGE_L2_L3"));
        PHASE_TO_PHASE_VOLTAGE_L3_L1 = deviceConfig.getInteger(("PHASE_TO_PHASE_VOLTAGE_L3_L1"));
    }

    /**
     * Concatenate bytes array to integer number
     * @param bytesArray bytes array
     * @return integer number
     */
    private int bytesArrayToNumber(byte[] bytesArray) {
        int buffer = 0;
        for (byte aBytesArray : bytesArray) {
            buffer = (buffer << BYTE_SIZE) | (aBytesArray < 0 ? aBytesArray + 256 : aBytesArray);
        }
        return buffer;
    }
}

